
skip_docs
default_platform(:ios)

platform :ios do

  desc "Runs the test target, which executes all the unit tests for each module
  within the SDK"
  lane :unit_tests do
    sh("
      set -o pipefail && xcodebuild \
      -workspace '../PayPal.xcworkspace' \
      -sdk 'iphonesimulator' \
      -configuration 'Debug' \
      -scheme 'UnitTests' \
      -destination 'name=iPhone 12,platform=iOS Simulator' \
      test | xcpretty
      ")
  end

  desc "Runs the test suite and calculates code coverage percentages for each
  module within the SDK"
  lane :coverage do
    MINIMUM_COVERAGE = 80.0

    # Run the test lane to get coverage profdata files
    unit_tests

    # Ensure the code coverage directory is empty before creating new coverage
    sh("rm -rf coverage")

    # Use xcov to get the coverage percentages
    xcov(
      scheme: "Demo",
      workspace: "PayPal.xcworkspace",
      output_directory: "fastlane/coverage",
      configuration: "Debug",
      json_report: true,
      ignore_file_path: "fastlane/.xcovignore",
    )

    # Interpret JSON report and output relevant coverage data
    UI.header "Coverage Data"
    file = File.open "coverage/report.json"
    data = JSON.load file

    targets = data["targets"]

    # Iterate through all of the targets. If any target is below our minimum
    # coverage percentage, iterate through that target's files and output the
    # coverage data of ones that are poorly tested
    total_coverage_data = data["targets"].map {|target|
      coverage = get_coverage(target, 0)

      if coverage < MINIMUM_COVERAGE
        filesForOutput = target["files"].each {|file|
          file_coverage = get_coverage(file, 1)

          if file_coverage < MINIMUM_COVERAGE
            file["functions"].each {|function|
              get_coverage(function, 2)
            }
          end
        }
      end
      UI.message ""
      coverage
    }

    #If the overall coverage percentage for any module is below our minimum threshhold, fail the test
    if total_coverage_data.any? {|target_percent| target_percent < MINIMUM_COVERAGE }
      UI.user_error!("Failure: All frameworks must have at least #{MINIMUM_COVERAGE}% code coverage")
    end
  end

  desc "Get code coverage data from the input JSON dictionary, output it to the
  terminal, and return the coverge percentage"
  def get_coverage(hash, indent_count)
    name = hash["name"]
    coverage = hash["coverage"].to_f * 100
    indentation = "\t" * indent_count
    output = indentation + "#{name}: #{coverage}%"
    coverage < MINIMUM_COVERAGE ? UI.error(output) : UI.success(output)
    return coverage
  end

  desc "Runs SwiftLint and returns any errors if our linter rule aren't met"
  lane :lint do
    swiftlint(
      mode: :lint,
      config_file: ".swiftlint.yml",
      raise_if_swiftlint_error: true,
      strict: true
    )
  end
end
